// @Name    : cai_error_handlers
// @author  : simon
// @date    : 2025/5/21 13:32
// @desc    :

import 'package:dio/dio.dart';

abstract class CaiErrorHandler {
  DioException handle(dynamic error);
}

class FormatErrorHandler extends CaiErrorHandler {
  @override
  DioException handle(error) {
    return DioException(
      requestOptions: RequestOptions(path: ''),
      message: error.message,
      error: error,
      type: DioExceptionType.unknown,
    );
  }
}

// 服务器发生错误
// DioExceptionType.badResponse:The status code of 500 has the following meaning: "Server error -
// the server failed to fulfil an apparently valid request"
class ServerErrorHandler extends CaiErrorHandler {
  @override
  DioException handle(error) {
    return error.copyWith(
        message: '服务器发生错误，请联系服务端技术员 (${error.response?.statusCode ?? -1})');
  }
}

class NetworkErrorHandler implements CaiErrorHandler {
  @override
  DioException handle(error) {
    return error.copyWith(
      message: '网络连接异常，请检查网络设置(${error.response?.statusCode ?? -1})',
      type: DioExceptionType.connectionError,
    );
  }
}

//DioExceptionType.unknown
class DefaultErrorHandler extends CaiErrorHandler {
  @override
  DioException handle(error) {
    final message = error.message?.contains('Invalid port') ?? false
        ? '没有这个企业码，请输入有效的唯一企业码 (${error.response?.statusCode ?? -1})'
        : error.message;
    return error.copyWith(message: message);
  }
}

class ReceiveTimeoutErrorHandler extends CaiErrorHandler {
  @override
  DioException handle(error) {
    final message = '网络开小差了，请稍后再试 (${error.response?.statusCode ?? -1})';
    return error.copyWith(message: message);
  }
}

// 增强错误处理
class GroupCancelHandler extends CaiErrorHandler {
  @override
  DioException handle(error) {
    if (error.type == DioExceptionType.cancel) {
      return error.copyWith(
        message: '请求已取消: ${error.message}',
        error: 'USER_CANCELLED',
      );
    }
    return error;
  }
}

// 在 ErrorHandlerFactory 添加智能错误识别
// （已确认）安卓：没有网络连接线上域名的时候返回这个。connectionTimeout:DioException [connection timeout]: The request connection
// // took longer than 0:00:10.000000 and it was aborted. To get rid of this exception,
// // try raising the RequestOptions.connectTimeout above the duration of 0:00:10.00
// or improve the response time of the server.
class ErrorHandlerFactory {
  static CaiErrorHandler getHandler(DioException e) {
    final statusCode = e.response?.statusCode;
    // 根据状态码优先处理
    if (statusCode != null) {
      //服务器错误
      if (statusCode >= 500) {
        return ServerErrorHandler();
      }
      //4xx ------- 客户端错误类 (请求错误)
      //（未授权）->请求要求身份验证。 对于需要登录的网页，服务器可能返回此响应。
      // if (statusCode == 401) {
      //   return AuthErrorHandler();
      // }
    }else{
      //没有连接上服务的时候，是没有statusCode的；
    }
    // 按类型处理
    switch (e.type) {
      case DioExceptionType.connectionError:
        if (e.error == 'NETWORK_UNAVAILABLE') {
          return NetworkErrorHandler();
        }
        return _isHostUnreachable(e)
            ? NetworkErrorHandler()
            : ServerErrorHandler();
      case DioExceptionType.sendTimeout:
        return NetworkErrorHandler();
    //connectionTimeout：如果我自己设置的时间比较短，又到了时间，其实是服务器不行导致，这种该如何区分？
    // 暂时一律按服务端异常处理。
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.badResponse:
        return ServerErrorHandler();
      case DioExceptionType.receiveTimeout:
        return ReceiveTimeoutErrorHandler();
      case DioExceptionType.cancel:
        return GroupCancelHandler();
      default:
        return DefaultErrorHandler();
    }
  }

  static bool _isHostUnreachable(DioException e) {
    return e.message?.contains('Failed host lookup') ?? false;
  }
}
